﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

using RpgLibrary;
using RpgLibrary.ItemClasses;
using RpgLibrary.CharacterClasses;
using RpgLibrary.SkillClasses;

namespace RpgEditor
{
    public partial class FormDataList<DetailFormType, DataObjectType> : Form
        where DetailFormType : IDisposable, IDetailForm, new()
        where DataObjectType : IRpgDataObject
    {
        protected Dictionary<string, DataObjectType> DataDictionary;
        protected string DataObjectPath;

        private string selectedEntityName = string.Empty;
        protected string SelectedEntityName
        {
            get
            {
                if (String.IsNullOrEmpty(selectedEntityName))
                {
                    string detail = lbDetails.SelectedItem.ToString();
                    int firstCommaIndex = detail.IndexOf(',');
                    if (firstCommaIndex > -1)
                        selectedEntityName = detail.Substring(0, firstCommaIndex).Trim();
                    else
                        selectedEntityName = detail;
                }

                return selectedEntityName;
            }
        }

        protected string FormTitle
        {
            get
            {
                return DataObjectPath.Substring(DataObjectPath.LastIndexOf(@"\")+1);
            }
        }

        #region Constructor Region
        public FormDataList(Dictionary<string, DataObjectType> dataDictionary, string dataObjectPath)
        {
            InitializeComponent();

            DataDictionary = dataDictionary;
            DataObjectPath = dataObjectPath;

            this.Text = FormTitle;

            this.FormClosing += new FormClosingEventHandler(FormDetails_FormClosing);
            btnAdd.Click += new EventHandler(btnAdd_Click);
            btnEdit.Click += new EventHandler(btnEdit_Click);
            btnDelete.Click += new EventHandler(btnDelete_Click);

            
            FillListBox(DataDictionary);
        }
        #endregion

        #region Event Handler Region
        
        void FormDetails_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                e.Cancel = true;
                selectedEntityName = string.Empty;
                this.Hide();
            }

            if (e.CloseReason == CloseReason.MdiFormClosing)
            {
                e.Cancel = false;
                this.Close();
            }
        }

        void btnAdd_Click(object sender, EventArgs e)
        {
            AddClickHelper<DetailFormType, DataObjectType>(DataDictionary);
        }

        void btnEdit_Click(object sender, EventArgs e)
        {
            EditClickHelper<DetailFormType, DataObjectType>(DataDictionary);
        }

        void btnDelete_Click(object sender, EventArgs e)
        {
            DeleteListItem(DataDictionary, DataObjectPath);
        }

        #endregion

        #region Methods

        protected void EditClickHelper<FormType, DataType>(Dictionary<string, DataType> dataDictionary)
            where FormType : IDisposable, IDetailForm, new()
            where DataType : IRpgDataObject
        {
            if (lbDetails.SelectedItem != null)
            {
                if (dataDictionary[SelectedEntityName] != null)
                {
                    IRpgDataObject data = dataDictionary[SelectedEntityName];
                    IRpgDataObject newData = null;

                    using (FormType frmEditData = new FormType())
                    {
                        frmEditData.DataObject = data;
                        DialogResult r = frmEditData.ShowDialog();
                        if (r == DialogResult.OK)
                        {
                            if (frmEditData.DataObject.Name == SelectedEntityName)
                            {
                                dataDictionary[SelectedEntityName] = (DataType)frmEditData.DataObject;
                                FillListBox(dataDictionary);
                                return;
                            }

                            newData = frmEditData.DataObject;
                        }
                        else
                            return;
                    }

                    DialogResult result = MessageBox.Show(
                        "Name has changed. Do you want to add a new entry?",
                        "New Entry",
                        MessageBoxButtons.YesNo);

                    if (result == DialogResult.Yes)
                    {
                        if (dataDictionary.ContainsKey(newData.Name))
                        {
                            MessageBox.Show("Entry already exists. Use Edit to modify the entry.");
                            return;
                        }

                        lbDetails.Items.Add(newData);
                        dataDictionary.Add(newData.Name, (DataType)newData);
                    }
                }
            }
        }

        protected void AddClickHelper<FormType, DataType>(Dictionary<string, DataType> dataDictionary) 
            where FormType : IDisposable, IDetailForm, new()
            where DataType : IRpgDataObject
        {

            using (FormType detailsForm = new FormType())
            {
                bool finishedAdding = false;
                do
                {
                    detailsForm.ShowDialog();
                    if (detailsForm.DataObject != null)
                    {
                        finishedAdding = AddDataObject<DataType>(detailsForm.DataObject, dataDictionary);
                    }
                    else
                        finishedAdding = true;

                } while (!finishedAdding);

            }
        }

        protected bool AddDataObject<T>(IRpgDataObject dataObject, Dictionary<string, T> dataDictionary)
        {
            if (dataDictionary.ContainsKey(dataObject.Name))
            {
                DialogResult result = MessageBox.Show(
                    dataObject.Name + " already exists. Overwrite it?",
                    "Name already exists",
                    MessageBoxButtons.YesNo);

                if (result == DialogResult.No)
                    return false;

                dataDictionary[dataObject.Name] = (T)dataObject;

                FillListBox(dataDictionary);
                return true;
            }

            dataDictionary.Add(dataObject.Name, (T)dataObject);
            lbDetails.Items.Add(dataObject);

            return true;
        }

        protected void FillListBox(System.Collections.IDictionary dictionary)
        {
            lbDetails.Items.Clear();
            foreach (string s in dictionary.Keys)
                lbDetails.Items.Add(dictionary[s]);
        }

        protected void DeleteListItem(System.Collections.IDictionary dictionary, string DataObjectPath)
        {
            if (lbDetails.SelectedItem != null)
            {
                DialogResult result = MessageBox.Show(
                    "Are you sure you want to delete " + SelectedEntityName + "?",
                    "Delete",
                    MessageBoxButtons.YesNo);

                if (result == DialogResult.Yes)
                {
                    lbDetails.Items.RemoveAt(lbDetails.SelectedIndex);
                    dictionary.Remove(SelectedEntityName);
                    if (File.Exists(Path.Combine(DataObjectPath, SelectedEntityName + ".xml")))
                        File.Delete(Path.Combine(DataObjectPath, SelectedEntityName + ".xml"));
                }
            }
        }

        

        

        
        #endregion

        private void lbDetails_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lbDetails.SelectedIndex > -1)
                selectedEntityName = string.Empty;
        }
    }
}